<?php
/*
框架核心类，供子类继承
*/
abstract class Base {

	/*
	返回被请求的文件名
	*/
	public function RequestFile() {
		$request_name=$this->Get('request_file');
		return $request_name;
	}

	//去除文件名中前后两端的-字符
	private function TrimFile($str) {
		if ($str=='') {
			return $str;
		}
		if (substr($str, 0, 1)=='-') {
			$str=substr($str, 1);
		}
		if (substr($str, -1, 1)=='-') {
			$str=substr($str, 0, strlen($str)-1);
		}
		return $str;
	}

	/*
	URI分解示例
	/news/				view				-1			-2			.html
	控制器class名			控制器function名		参数1的值		参数2的值	
	*/
	function URI() {
		$class_path='/';	//控制器文件路径
		$class_name='Index';	//控制器名
		$func_name='';	//方法名
		$func_par=array();	//方法参数数组
		//获取完整的URI
		$request_file=$this->RequestFile();

		//按/符号分解URI
		$request_arr=explode('/', $request_file);
		//过滤URI(/)中的空数组，防止出现uri结尾有/和没有/的不同
		$request_arr=array_filter($request_arr);
		//计算URI(/)数组的长度
		$request_arr_len=count($request_arr);

		//根据URI(/)数组的长度来分解其它部份
		switch ($request_arr_len) {
			//如果没有出现/，则视为访问首页
			case 0:
				break;
			//如果/出现1次，则视为访问根目录下的文件，或二级目录的首页
			//例如/test/或/test.html
			case 1:
				//如果URI中没有文件名，则视为访问二级目录的首页
				if (strpos($request_arr[$request_arr_len], '.')==false) {
					//控制器名为数组的最后一个索引值
					$class_name=$request_arr[$request_arr_len];
				}
				//如果URI中有文件名，则视为访问根目录中的文件
				else {
					//过滤字符串前后两端的-符号
					$request_arr[$request_arr_len]=$this->TrimFile($request_arr[$request_arr_len]);
					//将文件名以-号分隔成参数数组
					$file_name_arr=explode('-', $request_arr[$request_arr_len]);
					//计算数数组的长度
					$file_name_arr_len=count($file_name_arr);
					//如果文件名数组长度=1
					if ($file_name_arr_len==1) {
						//参数名为不包含后缀名的文件名
						$func_name=substr($request_arr[$request_arr_len], 0, strpos($request_arr[$request_arr_len], '.'));
					}
					else {
						//参数名为按-分隔的第一部份
						$func_name=$file_name_arr[0];
						//参数值为按-分隔的数组
						$func_par=$file_name_arr;
						//计算参数值数组的长度
						$func_par_len=count($func_par);
						//删除参数数组中的方法索引[0]，并重新排序索引
						array_splice($func_par, 0, 1);
						//计算参数值数组的长度
						$func_par_len=count($func_par);
						//如果有参数值
						if ($func_par_len>0) {
							//把参数值最后一个索引值中的文件后缀名去除
							$func_par[$func_par_len-1]=substr($func_par[$func_par_len-1], 0, strrpos($func_par[$func_par_len-1], '.'));
						}

					}
				}
				break;
			default:
				$for_end=$request_arr_len-1;
				//如果没有指定具体文件名
				if (strpos($request_arr[$request_arr_len], '.')==false) {
					//把路径数组拼接成路径，排除掉第一个数组(控制器名)
					for ($i=1; $i<=$for_end; $i++) {
						$class_path.=$request_arr[$i].'/';
					}
					$class_name=$request_arr[$request_arr_len];
				}
				else {
					$for_end-=1;
					for ($i=1; $i<=$for_end; $i++) {
						$class_path.=$request_arr[$i].'/';
					}
					//过滤字符串前后两端的-符号
					$request_arr[$request_arr_len]=$this->TrimFile($request_arr[$request_arr_len]);
					$file_name_arr=explode('-', $request_arr[$request_arr_len]);	//将文件名以-号分隔成数组
					$file_name_arr_len=count($file_name_arr);
					if ($file_name_arr_len==1) {
						$func_name=substr($request_arr[$request_arr_len], 0, strpos($request_arr[$request_arr_len], '.'));
					}
					else {
						$func_name=$file_name_arr[0];
						$func_par=$file_name_arr;
						//删除参数数组中的方法索引，并重新排序索引
						array_splice($func_par, 0, 1);
						//计算参数值数组的长度
						$func_par_len=count($func_par);
						//如果有参数值
						if ($func_par_len>0) {
							$func_par[$func_par_len-1]=substr($func_par[$func_par_len-1], 0, strrpos($func_par[$func_par_len-1], '.'));
						}
					}
					$class_name=$request_arr[$request_arr_len-1];
				}
				break;
		}
		$return['class_path']=$class_path;	//控制器文件路径
		$return['class_name']=$class_name;	//控制器名
		$return['func_name']=$func_name;	//方法名
		$return['func_par']=$func_par;		//方法参数数组
		return $return;
	}

	/*
	加载并自动实例化控制器文件，只需要路径和文件名，不包含后缀名
	*/
	function Inc($file_path='/', $file_name='', $file_type='', $var=array()) {
		switch ($file_type) {
			//加载控制器，并返回自动实例化后的对象，不用加.php文件后缀名
			case 'c':
				if ($file_name=='') {
					$file_name='index';
				}
				$file=root_path.'/'.controller_path.'/'.$file_path.'/'.$file_name.'.php';
				if (file_exists($file)) {
					require_once($file);
					if (class_exists($file_name)) {
						return new $file_name();
					}
					else {
						$this->Header(404);
					}
				}
				else {
					$this->Header(404);
				}
				break;
			//加载模型，并返回自动实例化后的对象，不用加.php文件后缀名
			case 'm':
				if ($file_name=='') {
					$file_name='index';
				}
				$file=root_path.'/'.model_path.'/'.$file_path.'/'.$file_name.'.php';
				if (file_exists($file)) {
					require_once($file);
					if (class_exists($file_name)) {
						return new $file_name();
					}
					else {
						$this->Header(404);
					}
				}
				else {
					$this->Header(404);
				}
				break;
			//加载函数库，不用加.php文件后缀名
			case 'f':
				$file=root_path.'/'.function_path.'/'.$file_name.'.php';
				if (file_exists($file)==false) {
					$this->Header(404);
				}
				else {
					return true;
				}
				break;
			//加载视图文件，并传入页面变量，需要自己加文件后缀名
			case 'v':
				foreach ($var as $longqing_key=>$longqing_value) {
					${$longqing_key}=$longqing_value;
				}
				//如果控制器是根目录下的文件
				$longqing_file=root_path.'/'.view_path.'/'.$file_path.'/'.$file_name;
				unset($file_path);
				unset($file_name);
				unset($var);
				unset($longqing_value);
				if (file_exists($longqing_file)==false) {
					$this->Header(404);
				}
				else {
					require($longqing_file);
				}
				break;
			//加载普通文件，需要自己加路径和文件后缀名
			default:
				$file=$file_path.'/'.$file_name;
				if (file_exists($file)==false) {
					$this->Header(404);
				}
				else {
					require_once($file);
				}
				break;
		}
	}

	/*
	输出HTTP Header信息并退出程序
	*/
	function Header($http_code=404, $url='') {
		switch ($http_code) {
			//404未找到文件
			case 404:
				if (page_404=='') {	//如果自定义错误
					header('HTTP/1.1 404 Not Found');
					header("status: 404 Not Found");
				}
				else {
					$file=root_path.'/'.view_path.'/'.page_404;
					if (file_exists($file)==false) {
						header('HTTP/1.1 404 Not Found');
						header("status: 404 Not Found");
					}
					else {
						require_once($file);
					}
				}
				break;
			//301永久重定向
			case 301:
				header('HTTP/1.1 301 Moved Permanently');
				header('Location: '.$url);
				break;
			//302临时重定向
			case 302:
				header('Location: '.$url);
				break;

		}
		exit();
	}

	/*
	中断并输出错误信息到指定页面
	*/
	function Error($msg, $display_error=display_error) {
		$file=root_path.'/'.view_path.'/'.page_error;
		if (file_exists($file)==false) {
			$this->Header(404);
		}
		else {
			require($file);
		}
		exit();
	}

	/*
	写入信息到日志文件
	$msg 信息字符串
	line 代码行数或信息编号
	*/
	function Log($line, $msg) {
		$file=fopen(root_path.'/'.log_path.'/'.date('Y-m-d').'.log', 'a');
		$content='Time:'.date('H:i:s')."\r\nURI:".$_SERVER['REQUEST_URI']."\r\nLine:".$line."\r\nMessage:".$msg;
		if ($file) {
			fwrite($file, $content."\r\n\r\n");
			fclose($file);
		}
	}

	/*
	返回客户端IP
	$type=false时返回IP字符串
	$typt=true时，返回long类型的IP
	*/
	function ClientIP($type=false) {
		if(getenv('HTTP_CLIENT_IP')) {
			$ip=getenv('HTTP_CLIENT_IP');
		}
		elseif(getenv('HTTP_X_FORWARDED_FOR')) {
			$ip=getenv('HTTP_X_FORWARDED_FOR');
		}
		elseif(getenv('REMOTE_ADDR')) {
			$ip=getenv('REMOTE_ADDR');
		}
		else {
			$ip=$HTTP_SERVER_VARS['REMOTE_ADDR'];
		}
		if($type==false) {
			return $ip;
		}
		elseif($t==true) {
			return sprintf('%u',bindec(decbin(ip2long($ip))));
		}
	}

	/*
	删除目录以其文件和子目录
	*/
	function RmDir($dir) {
		if (is_dir($dir)) {
			$objects = scandir($dir);
			foreach ($objects as $object) {
				if ($object != '.' && $object != '..') {
					if (filetype($dir.'/'.$object) == 'dir') {
						if (!rmdir($dir.'/'.$object)) {
							return false;
						}
					}
					else {
						if (!unlink($dir.'/'.$object)) {
							return false;
						}
					}
				}
			}
			reset($objects);
			if (!rmdir($dir)) {
				return false;
			}
		}
		return true;
	}

	//获取GET参数值
	function Get($parameter, $type='str') {
		$value='';
		//如果GET参数值存在
		if (isset($_GET[$parameter])) {
			//获得GET参数值
			$value=$_GET[$parameter];
			switch ($type) {
				case 'str':
					$value=strval(htmlspecialchars($value));
					break;
				case 'int':
					$value=intval(htmlspecialchars($value));
					break;
				case 'float':
					$value=floatval(htmlspecialchars($value));
					break;
				default:
					$value=htmlspecialchars($value);
					break;
			}
		}
		else {
			switch ($type) {
				case 'str':
					$value='';
					break;
				default:
					$value=0;
					break;
			}
		}
		return $value;
	}

	//获取POST参数值
	function Post($parameter, $type='str') {
		$value='';
		//如果GET参数值存在
		if (isset($_POST[$parameter])) {
			//获得GET参数值
			$value=$_POST[$parameter];
			switch ($type) {
				case 'str':
					$value=strval(htmlspecialchars($value));
					break;
				case 'int':
					$value=floatval(htmlspecialchars($value));
					break;
				case 'float':
					$value=floatval(htmlspecialchars($value));
					break;
				case 'array':
					foreach ($value as $key=>$v) {
						$value[$key]=htmlspecialchars($v);
					}
					break;
				default:
					$value=htmlspecialchars($value);
					break;
			}
		}
		else {
			switch ($type) {
				case 'str':
					$value='';
					break;
				default:
					$value=0;
					break;
			}
		}
		return $value;
	}
}
?>